import time

from pi.dao.moveDao import moveDao
from pi.model.instruction import instruction

"""
    根据四个按钮的状态，指导小车运动
    四个按钮都有按下和松开两种状态
"""


class moveController:
    # 分别表示四个按钮被按下的状态 1表示被按下
    _u_button = False
    _d_button = False
    _l_button = False
    _r_button = False
    _speed = 50
    _diff_speed = 20
    _trace_stack = None
    _move = None
    own_trace_stack = []  # 当前类的路径，与上面的区别是，这是在这个类创建之后执行的路径

    def __init__(self, trace_stack):
        self._trace_stack = trace_stack
        self._u_button, self._d_button, self._l_button, self._r_button = False, False, False, False
        self._move = moveDao()

    def get_speed(self) -> int:
        return self._speed

    def _flush(self, instruct: instruction):
        """
        刷新按钮状态
        :param dir_dict:
        :return:
        """
        self._u_button = instruct.direction[0]
        self._d_button = instruct.direction[1]
        self._l_button = instruct.direction[2]
        self._r_button = instruct.direction[3]
        self._speed = instruct.speed
        self._diff_speed = instruct.diff_speed
        print(">>> 新状态：", instruct.direction, self._speed, self._diff_speed)

    def run(self, instruct: instruction):
        """
        读取当前状态，小车开始运行（小车可能已经在运行，那么就是修改运动状态）
        :return:
        """
        instruct.set_time_current()  # 先把时间改成当前时间
        self._trace_stack.append(instruct.to_json())  # 存储执行的指令
        self.own_trace_stack.append(instruct.to_json())
        """下面开始判断指令类型"""

        """下面是具体的运动"""

        # dir_dict = instruct.direction
        self._flush(instruct)  # 先刷新按钮
        button_sum = self._u_button + self._d_button + self._l_button + self._r_button
        if button_sum in [0, 4]:
            self._move.t_stop(-1)  # 不动
        elif button_sum == 1:  # 一个按钮按下，直接移动即可
            if self._u_button:
                self._move.t_up(speed=self._speed)
            elif self._d_button:
                self._move.t_down(speed=self._speed)
            elif self._l_button:
                self._move.t_left_local(speed=self._speed)
            elif self._r_button:
                self._move.t_right_local(speed=self._speed)
        elif button_sum == 2:  # 按下两个按钮，共六种情况
            if (self._u_button and self._d_button) or (self._l_button and self._r_button):  # 按下反方向按键，互相抵消
                self._move.t_stop(t_time=-1)
            elif self._u_button and self._l_button:  # 左转
                self._move.t_left(speed=self._speed, diff_speed=self._diff_speed)
            elif self._u_button and self._r_button:  # 右转
                self._move.t_right(speed=self._speed, diff_speed=self._diff_speed)
            elif self._d_button and self._l_button:  # 车尾往右退
                self._move.t_right(speed=-1 * self._speed, diff_speed=self._diff_speed)
            elif self._d_button and self._r_button:  # 车尾往左退
                self._move.t_left(speed=-1 * self._speed, diff_speed=self._diff_speed)
        elif button_sum == 3:  # 一个按钮按下，反向移动即可，类似一个按钮
            if not self._u_button:
                self._move.t_up(speed=self._speed)
            elif not self._d_button:
                self._move.t_down(speed=self._speed)
            elif not self._l_button:
                self._move.t_left_local(speed=self._speed)
            elif not self._r_button:
                self._move.t_right_local(speed=self._speed)
        else:
            raise ValueError("button_sum", button_sum)

    def run_back_home(self, trace_list: list = None):
        """
        todo：将trace_stack内的指令反向执行一遍，注意时间，注意截取最近一次从家出发之后的指令
        :param trace_list: 可以指定回家的路径（服务器计算最近的路径）
        :return:
        """
        pass

    def stop(self, t_time=0):
        self._move.t_stop(-1)  # 不动
        time.sleep(t_time)

    def get_trace_stack(self) -> list:
        return self._trace_stack

    def clear_trace_stack(self) -> bool:
        self._trace_stack = []
        return True

    def get_cur_instruction(self) -> instruction:
        """
        获得当前指令（在外部可用于保存当前状态）
        :return:  返回指令栈的最后一个元素即可
        """
        return self._trace_stack[-1]

